package cc.shacocloud.mirage.context.restful;

import cc.shacocloud.mirage.bean.ObjectProvider;
import cc.shacocloud.mirage.bean.bind.Autowired;
import cc.shacocloud.mirage.bean.bind.Bean;
import cc.shacocloud.mirage.bean.bind.Configuration;
import cc.shacocloud.mirage.bean.bind.Prototype;
import cc.shacocloud.mirage.core.bind.ConditionalOnClass;
import cc.shacocloud.mirage.core.bind.ConditionalOnMissingBean;
import cc.shacocloud.mirage.restful.*;
import cc.shacocloud.mirage.restful.bind.converter.json.Jackson2ObjectMapperBuilder;
import cc.shacocloud.mirage.restful.bind.validation.SmartValidator;
import cc.shacocloud.mirage.restful.bind.validation.SmartValidatorImpl;
import cc.shacocloud.mirage.utils.comparator.OrderComparator;
import cc.shacocloud.mirage.utils.converter.TypeConverterSupport;
import cc.shacocloud.mirage.utils.reflection.ParameterNameDiscoverer;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.vertx.core.Vertx;
import jakarta.validation.Validation;
import jakarta.validation.ValidatorFactory;
import org.hibernate.validator.HibernateValidator;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Constructor;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Mirage Restful 配置启动类
 *
 * @author shaco
 */
@Configuration
@ConditionalOnClass("cc.shacocloud.mirage.restful.MirageRequestMappingHandler")
public class MirageRestfulConfiguration {
    
    public static final String MIRAGE_WEB_SERVER_VERTICLE_BEAN_NAME = "mirageWebServerVerticle";
    
    /**
     * {@link MirageWebServerVerticle} 的参数配置对象
     *
     * @see #routerFilterMappingHandler
     * @see #requestMappingHandler
     */
    @Bean
    @ConditionalOnMissingBean
    public MirageWebServerOptions webServerOptions(MirageRestfulConfigProperties webMvcConfigProperties,
                                                   @NotNull ObjectProvider<RouterMappingHandler> routerMappingHandlerObjectProvider) {
        // 路由映射处理器
        List<RouterMappingHandler> routerMappingHandlers = routerMappingHandlerObjectProvider.stream()
                .sorted(OrderComparator.INSTANCE)
                // 路由映射处理器初始化
                .peek(RouterMappingHandler::init)
                .collect(Collectors.toList());
        
        return new MirageWebServerOptions(webMvcConfigProperties, routerMappingHandlers);
    }
    
    /**
     * 基于 vertx 核心机制，将web服务部署成一个站点
     */
    @Prototype
    @Bean(MIRAGE_WEB_SERVER_VERTICLE_BEAN_NAME)
    @ConditionalOnMissingBean(name = MIRAGE_WEB_SERVER_VERTICLE_BEAN_NAME)
    public MirageWebServerVerticle webServerVerticle(MirageWebServerOptions mirageWebServerOptions) {
        return new MirageWebServerVerticle(mirageWebServerOptions);
    }
    
    /**
     * 参数验证对象
     */
    @Bean
    @ConditionalOnMissingBean
    public SmartValidator smartValidator() {
        try (ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                .failFast(false)
                .buildValidatorFactory()) {
            
            return new SmartValidatorImpl(validatorFactory.getValidator());
        }
    }
    
    /**
     * jackson 定制的{@link ObjectMapper}
     */
    @Bean
    @ConditionalOnMissingBean
    public ObjectMapper objectMapper() {
        return Jackson2ObjectMapperBuilder.json().build();
    }
    
    /**
     * 基于 Bean {@link HandlerMethod} 的请求映射处理器
     *
     * @see VertxRouterRequestMappingMappingRequestHandler
     * @see HandlerMethod
     */
    @Bean
    @ConditionalOnMissingBean
    public MirageRequestMappingHandler requestMappingHandler(Vertx vertx,
                                                             ObjectMapper objectMapper,
                                                             @Autowired(required = false) SmartValidator validator,
                                                             @Autowired(required = false) TypeConverterSupport typeConverterSupport,
                                                             ParameterNameDiscoverer parameterNameDiscoverer) throws Exception {
        MirageRequestMappingHandler mirageRequestMappingHandler;
        try {
            // 优先使用 kotlin
            Class<?> clazz = Class.forName("cc.shacocloud.mirage.kotlin.restful.KotlinRequestMappingHandler");
            Constructor<?> constructor = clazz.getConstructor(Vertx.class, ParameterNameDiscoverer.class, ObjectMapper.class);
            mirageRequestMappingHandler = (MirageRequestMappingHandler) constructor.newInstance(vertx, parameterNameDiscoverer, objectMapper);
        } catch (ClassNotFoundException ex) {
            mirageRequestMappingHandler = new MirageRequestMappingHandler(vertx, parameterNameDiscoverer, objectMapper);
        }
        
        mirageRequestMappingHandler.setValidator(validator);
        mirageRequestMappingHandler.setTypeConverterSupport(typeConverterSupport);
        return mirageRequestMappingHandler;
    }
    
    /**
     * 基于Bean的路由过滤器
     *
     * @see VertxRouterFilterMappingHandler
     * @see Filter
     */
    @Bean
    @ConditionalOnMissingBean
    public MirageRouterFilterMappingHandler routerFilterMappingHandler() {
        return new MirageRouterFilterMappingHandler();
    }
    
}
